Skip to content

refactor: remove ToggleButton - #5095

Merged
satya164 merged 4 commits into
callstack:mainfrom
oleksandrzavarzin-callstack:refactor/remove-toggle-button
Sep 15, 2026
Merged

satya164 merged 4 commits into
callstack:mainfrom
oleksandrzavarzin-callstack:refactor/remove-toggle-button

Conversation

@oleksandrzavarzin-callstack

Copy link
Copy Markdown
Contributor

Motivation

ToggleButton predates the Material Design 3 work and has no place in the v6
component set. MD3 has no equivalent component, and both of its use cases are
already covered by components we keep:

  • an icon-only toggle is IconButton with selected
  • a set of mutually exclusive options is SegmentedButtons

It is removed outright, with no deprecation alias and no runtime warning, per
the v6 rule against deprecations.

What's removed

  • ToggleButton, ToggleButton.Group, ToggleButton.Row, and their utils
  • The four public exports: the component plus ToggleButtonProps,
    ToggleButtonGroupProps and ToggleButtonRowProps
  • Its test and snapshot
  • Its example screen and its entry in the example app's list
  • Its entries in docs/component-docs.config.ts and
    docs/src/data/screenshots.ts, which drive 6.x doc generation

Migration

Documented in docs/6.x/docs/guides/migration.md:

- <ToggleButton.Group value={value} onValueChange={setValue}>
-   <ToggleButton icon="format-bold" value="bold" />
- </ToggleButton.Group>
+ <IconButton
+   icon="format-bold"
+   selected={value === 'bold'}
+   onPress={() => setValue('bold')}
+ />

Its line in the guide's animated-style list is gone too, since the component no
longer exists to accept a style.

Notes for review

  • Ordering against the Button PR. The migration entry closes by noting that
    Button also gains a selected prop as part of its MD3 update. That prop
    arrives with refactor(button): improve MD3 compliance and modernize content API #4928, so if this lands first the sentence describes a prop not
    yet on main. It reads as forward-looking rather than wrong, but it is worth
    a look if the two land far apart. Every code example in the entry uses only
    APIs that exist on main today.

Test plan

  • yarn test, yarn lint, yarn typecheck pass: 54 suites, 669 tests, 1
    skipped, no obsolete snapshots.
  • The example app typechecks standalone (tsc -p example --noEmit).
  • yarn build in docs/ succeeds, and the built output has no 6.x
    ToggleButton page while the archived older-version pages are unchanged.
  • Grepped the tree for any remaining reference: the only ones left are the
    intentional migration entry and the 5.x docs.

BREAKING CHANGE: ToggleButton, ToggleButton.Group and ToggleButton.Row
are removed, along with ToggleButtonProps, ToggleButtonGroupProps and
ToggleButtonRowProps. Use IconButton with selected for an icon-only
toggle, or SegmentedButtons for a set of mutually exclusive options.

<>
<IconButton
icon="format-bold"
selected={value === 'bold'}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following this loses the selected state for screen readers: IconButton's selected only changes colours, while ToggleButton passed aria-selected through. Worth adding aria-selected to the snippet, or having IconButton derive it from selected?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JKobrynski, thank you for the comment! I've updated the migration docs with aria-selected.
As for deriving it from the selected one on the IconButton, I don't think that's in scope for this PR.
I can create a separate PR for it, or we can add it as a part of the IconButton modernization to MD3 (when that PR will be ready)

@JKobrynski JKobrynski left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM @satya164

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved accessibility and migration-behavior findings remain.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Removes the obsolete ToggleButton component family from v6 and updates examples and documentation to use current alternatives.

Changes:

  • Removes implementations, exports, tests, and snapshots.
  • Replaces tooltip controls and removes the obsolete example.
  • Updates documentation registrations and adds migration guidance.

Open findings include migration behavior and accessibility issues, plus stale screenshot assets.

File summaries
File Description
src/index.tsx Removes public component and type exports.
src/components/ToggleButton/utils.ts Removes toggle-specific utilities.
src/components/ToggleButton/ToggleButtonRow.tsx Removes row implementation.
src/components/ToggleButton/ToggleButtonGroup.tsx Removes group implementation.
src/components/ToggleButton/ToggleButton.tsx Removes base implementation.
src/components/ToggleButton/index.ts Removes compound exports.
src/components/__tests__/ToggleButton.test.tsx Removes obsolete tests.
src/components/__tests__/__snapshots__/ToggleButton.test.tsx.snap Removes obsolete snapshot.
example/src/Examples/TooltipExample.tsx Replaces controls with IconButton.
example/src/Examples/ToggleButtonExample.tsx Removes obsolete example.
example/src/ExampleList.tsx Removes example registration.
docs/src/data/screenshots.ts Removes screenshot mappings.
docs/component-docs.config.ts Removes documentation entries.
docs/6.x/docs/guides/migration.md Adds migration guidance.
Review details

Suppressed comments (5)

docs/6.x/docs/guides/migration.md:351

  • The removed ToggleButton group cleared the value when its already-selected item was pressed (!checked ? value : null). This replacement always writes 'bold', so copying the migration changes the behavior by making the active option impossible to deselect; preserve the null transition or explicitly document that behavior change.
    onPress={() => setValue('bold')}

docs/src/data/screenshots.ts:151

  • Removing the active screenshot mappings leaves the corresponding top-level assets (docs/public/screenshots/toggle-button.png, toggle-button-group.gif, toggle-button-row.gif, and docs/public/gallery/toggle-button.png) checked in but unreferenced. These are outside the versioned archived pages, so please remove the orphaned assets as part of the component removal to avoid carrying stale documentation files.
  },

example/src/Examples/TooltipExample.tsx:99

  • selected only changes IconButton's visual colors; it does not derive an accessibility state. This replacement therefore leaves the active alignment unavailable to screen readers, unlike the migration example below; pass the matching aria-selected value on this button (and the other two buttons).
                selected={textAlign === 'left'}

example/src/Examples/TooltipExample.tsx:107

  • This selected alignment control also omits aria-selected, so assistive technology cannot identify the active option. Add the matching accessibility state here as well as on the other icon toggles.
                selected={textAlign === 'center'}

example/src/Examples/TooltipExample.tsx:115

  • The disabled alignment control still represents a selected state, but selected is not exposed to assistive technology by IconButton. Add aria-selected here too so this replacement has consistent state semantics.
                selected={textAlign === 'right'}
  • Files reviewed: 14/14 changed files
  • Comments generated: 1
  • Review effort level: Lite (auto)

Note

Copilot is running an experiment and ran this review at Lite.


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/6.x/docs/guides/migration.md Outdated
Comment on lines +352 to +358
aria-selected={value === 'bold'}
/>
<IconButton
icon="format-italic"
selected={value === 'italic'}
onPress={() => setValue('italic')}
aria-selected={value === 'italic'}

@satya164 satya164 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks

@satya164
satya164 merged commit e98fce0 into callstack:main Sep 15, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants